package java8.stream;

import java8.Employee;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Stream的终止操作
 * 查找（findFirst、findAny）与匹配（allMatch、anyMatch、noneMatch）
 * max、min、count、forEach;
 * 归约（reduce）
 * 收集（collect）
 */
public class Stream3 {

    private static List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99, Employee.Status.FREE),
            new Employee("李四", 58, 5555.55, Employee.Status.BUSY),
            new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),
            new Employee("赵六", 36, 6666.66, Employee.Status.FREE),
            new Employee("田七", 12, 8888.88, Employee.Status.BUSY)
    );

    public static void main(String[] args) {
//        allMatch();
//        anyMatch();
//        noneMatch();

//        findFirst();
//        findAny();

//        count();
//        max();
//        min();

//        reduce();

//        collect_toCollection();
//        collect_joining();
//        collect_averagingDouble();
//        collect_summarizing();
//        collect_groupingBy1();
        collect_groupingBy2();
//        collect_partitioningBy();
    }

    public static void allMatch() {
        // 是否全都BUSY
        boolean b = employees.stream()
                .allMatch(e -> Objects.equals(e.getStatus(), Employee.Status.BUSY));
        System.out.println(b);
    }

    public static void anyMatch() {
        // 是否至少有一个BUSY
        boolean b = employees.stream()
                .anyMatch(e -> Objects.equals(e.getStatus(), Employee.Status.BUSY));
        System.out.println(b);
    }

    public static void noneMatch() {
        // 是否全都不BUSY
        boolean b = employees.stream()
                .noneMatch(e -> Employee.Status.BUSY.equals(e.getStatus()));
        System.out.println(b);
    }

    public static void findFirst() {
        // 获取薪水最低的那个
        Optional<Employee> first = employees.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary))
                .findFirst();
        System.out.println(first.get());
    }

    public static void findAny() {
        // 获取FREE状态的其中一个（使用并行流后每次先找到的那个可能不同）
        Optional<Employee> any = employees.parallelStream()
                .filter(e -> Employee.Status.FREE.equals(e.getStatus()))
                .findAny();
        System.out.println(any.get());
    }

    public static void count() {
        // 处于BUSY状态的总数
        long count = employees.stream()
                .filter(e -> Employee.Status.BUSY.equals(e.getStatus()))
                .count();
        System.out.println(count);
    }

    public static void max() {
        // 薪水最高的
        Optional<Employee> max = employees.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(max.get());
    }

    public static void min() {
        // 薪水最低的
        Optional<Double> min = employees.stream()
                .map(Employee::getSalary)
                .min(Double::compare);
        System.out.println(min.get());
    }

    public static void reduce() {
        // 计算薪水总和
        Double reduce1 = employees.stream()
                .map(Employee::getSalary)
                .reduce(0.0, Double::sum);
        System.out.println(reduce1);
    }

    public static void collect_toCollection() {
        // 将所有员工名字收集到HashSet中
        HashSet<String> hashSet = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(hashSet);
    }

    public static void collect_joining() {
        // 连接（返回字符串以"、"分隔，以"【"开始，以"】"结尾）
        String join = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining("、", "【", "】"));
        System.out.println(join);
    }

    public static void collect_averagingDouble() {
        // 计算薪水平均值
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);
    }

    public static void collect_summarizing() {
        // 薪水的组函数
        DoubleSummaryStatistics summaryStatistics = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println("max:" + summaryStatistics.getMax());
        System.out.println("min:" + summaryStatistics.getMin());
        System.out.println("avg:" + summaryStatistics.getAverage());
        System.out.println("sum:" + summaryStatistics.getSum());
        System.out.println("count:" + summaryStatistics.getCount());
    }

    public static void collect_groupingBy1() {
        // 分组
        Map<Employee.Status, List<Employee>> group = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        group.forEach((k, v) -> System.out.println(k + ":" + v));
    }

    public static void collect_groupingBy2() {
        // 多级分组（先按状态分，再按工资分）
        Map<Employee.Status, Map<String, List<Employee>>> group = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(e -> e.getSalary() > 6000 ? "财富自由" : "直接躺平")));
        group.forEach((k, v) -> System.out.println(k + ":" + v));
    }

    public static void collect_partitioningBy() {
        // 分区（只分true/false）
        Map<Boolean, List<Employee>> partition = employees.stream()
                .collect(Collectors.partitioningBy(e -> e.getAge() > 30));
        partition.forEach((k, v) -> System.out.println(k + ":" + v));
    }
}
